package it.tukano.swingdeco.input;

import it.tukano.collections.ListExt;
import it.tukano.fun.Function1;
import it.tukano.fun.VFunction1;
import it.tukano.swingdeco.containers.JPanelExt;
import it.tukano.swingdeco.controls.JButtonExt;
import it.tukano.swingdeco.list.JListExt;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JLabel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

/**
 * Input component wrapped in a JPopupMenu
 * @author pgi
 */
public class PopupInput {

    /**
     * Instance initializer
     */
    public PopupInput() {
    }
    
    public static <T> void showOptionListPopup(String title, Component parent, Iterable<T> items, final Function1<T, ?> onAccept) {
        final ListExt<T> listItems = ListExt.newListExt(items);
        final JPopupMenu popup = new JPopupMenu();
        final JListExt list = new JListExt().setValues(listItems);
        final JButtonExt accept = new JButtonExt("Ok").scaleFont(0.8).setDisabled();
        final Runnable acceptTask = new Runnable() {

            public void run() {
                popup.setVisible(false);
                int index = list.getSelectedIndex();
                if(index >= 0) {
                    onAccept.apply(listItems.get(index));
                }
            }
        };
        accept.onActionPerformed(acceptTask);
        JButtonExt cancel = new JButtonExt("Cancel").scaleFont(0.8).onActionPerformed(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                popup.setVisible(false);
            }
        });
        list.onSelectionSet(new Runnable() {

            public void run() {
                int index = list.getSelectedIndex();
                accept.setEnabled(index >= 0);
            }
        });
        list.onDoubleClick(new VFunction1<Object>() {

            @Override
            protected void doApply(Object p) {
                acceptTask.run();
            }
        });
        final JPanelExt panel = new JPanelExt(new BorderLayout())
                .append(new JScrollPane(list));
        final JPanelExt container = new JPanelExt(new BorderLayout()).
                append(panel, BorderLayout.CENTER,
                new JPanelExt(new FlowLayout(FlowLayout.RIGHT)).append(accept, cancel),
                BorderLayout.SOUTH).
                setTitledBorder("title");
        popup.add(container);
        popup.show(parent, 0, parent.getHeight());        
    }

    /**
     * Display a popup menu with a custom content
     * @param parent the parent of the popup
     * @param content the content of the popup
     * @param onAccept the action executed if the user presses the ok button
     * @param onCancel the action executed if the user pressed the cancel button
     */
    public static void showConfirmPopup(Component parent, Component content, final Runnable onAccept, final Runnable onCancel) {
        showConfirmPopup("Confirm", parent, content, new Point(0, parent.getHeight()), onAccept, onCancel);
    }

    public static JPopupMenu showConfirmPopup(String title, Component parent, Component content, Point location, final Runnable onAccept, final Runnable onCancel) {
        final JPopupMenu popup = new JPopupMenu();
        JButtonExt accept = new JButtonExt("Ok").scaleFont(0.8).onActionPerformed(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                popup.setVisible(false);
                if(onAccept != null) onAccept.run();
            }
        });
        JButtonExt cancel = new JButtonExt("Cancel").scaleFont(0.8).onActionPerformed(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                popup.setVisible(false);
                if(onCancel != null) onCancel.run();
            }
        });
        JPanelExt container = new JPanelExt(new BorderLayout()).
                append(content, BorderLayout.CENTER,
                new JPanelExt(new FlowLayout(FlowLayout.RIGHT)).append(accept, cancel),
                BorderLayout.SOUTH).
                setTitledBorder(title);
        popup.add(container);
        popup.show(parent, location.x, location.y);
        return popup;
    }

    /**
     * A popup dialog that asks the user to confirm something
     * @param parent the owner of the popup
     * @param text the text displayed in the confirm popup
     * @param onAccept the action that will be executed when the user presses ok
     * @param onCancel the action that will be executed when the user presses cancel
     */
    public static void showConfirmPopup(Component parent, String text, final Runnable onAccept, final Runnable onCancel) {
        final JPopupMenu popup = new JPopupMenu();
        final JLabel field = new JLabel(text);
        JButtonExt accept = new JButtonExt("Ok").scaleFont(0.8).onActionPerformed(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                popup.setVisible(false);
                if(onAccept != null) onAccept.run();
            }
        });
        JButtonExt cancel = new JButtonExt("Cancel").scaleFont(0.8).onActionPerformed(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                popup.setVisible(false);
                if(onCancel != null) onCancel.run();
            }
        });
        JPanelExt container = new JPanelExt(new BorderLayout()).
                append(field, BorderLayout.CENTER,
                new JPanelExt(new FlowLayout(FlowLayout.RIGHT)).append(accept, cancel),
                BorderLayout.SOUTH).
                setTitledBorder("Confirm");
        popup.add(container);
        popup.show(parent, 0, parent.getHeight());
    }

    /**
     * Displayes a popup menu that asks the user to type a string
     * @param parent the owner of the popup
     * @param title the title of the popup
     * @param fieldSize the size of the input text field (char count)
     * @param onAccept the action that will be executed when the user accepts the input (by
     * pressing the ok button or pressing enter on the the input field)
     */
    public static void showInputStringPopup(Component parent, String title, int fieldSize, final Function1<String, ?> onAccept) {
        showInputStringPopup(parent, new Point(0, parent.getHeight()), title, fieldSize, onAccept);
    }

    /**
     * Display a popup menu that asks the user to type a string
     * @param parent the parent of the popup menu
     * @param location the location of the menu relative to the parent
     * @param title the title of the popup
     * @param fieldSize the size (char count) of the text field
     * @param onAccept the function called when the user accepts the user input
     */
    public static void showInputStringPopup(Component parent, Point location, String title, int fieldSize, final Function1<String, ?> onAccept) {
        final JPopupMenu popup = new JPopupMenu();
        final JTextField field = new JTextField(fieldSize);
        ActionListener listener = new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                popup.setVisible(false);
                onAccept.apply(field.getText());
            }
        };
        JButtonExt button = new JButtonExt("Ok").onActionPerformed(listener);
        field.addActionListener(listener);
        JPanelExt container = new JPanelExt(new BorderLayout()).
                append(field, BorderLayout.CENTER, button, BorderLayout.EAST).
                setTitledBorder(title);
        popup.add(container);
        popup.show(parent, location.x, location.y);
        field.requestFocusInWindow();
    }
}
